package functions

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"runtime"
	"sort"
	"strings"

	"github.com/gobuffalo/packr/v2"
)

func ExecShell(strCommand string) string {
	var (
		name, arg string
		outBytes  []byte
		err       error
	)

	switch runtime.GOOS {
	case "linux":
		name, arg = "sh", "-c"
	case "windows":
		name, arg = "cmd", "/C"
	default:
		name, arg = "sh", "-c"
	}

	cmd := exec.Command(name, arg, strCommand)

	stdout, _ := cmd.StdoutPipe()
	if err = cmd.Start(); err != nil {
		fmt.Println("Execute failed when Start:"+err.Error(), "--", strCommand)
		return ""
	}

	outBytes, err = io.ReadAll(stdout)
	if err != nil {
		log.Fatal(err)
	}

	err = stdout.Close()
	if err != nil {
		log.Fatal(err)
	}

	if err = cmd.Wait(); err != nil {
		fmt.Println("Execute failed when Wait:"+err.Error(), "--", strCommand)
		return ""
	}
	return strings.Trim(strings.Trim(string(outBytes), ""), "\n")
}

func IsDir(src string) bool {
	s, err := os.Stat(src)
	if err != nil {
		return false
	}
	return s.IsDir()
}

func MakeDir(path string) {
	err := os.MkdirAll(path, 0777)

	if err != nil {
		log.Fatal(err)
	}
}

func ReadAll(filePth string) ([]byte, error) {
	f, err := os.ReadFile(filePth)
	if err != nil {
		return nil, err
	}

	return f, nil
}

func WriteToFileAppend(filePth, msg string) {
	writeToFile(filePth, msg, os.O_WRONLY|os.O_CREATE|os.O_APPEND)
}

func WriteToFileTrunc(filePth, msg string) {
	writeToFile(filePth, msg, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
}

func writeToFile(filePth, msg string, flag int) {
	var (
		file *os.File
		err  error
	)

	file, err = os.OpenFile(filePth, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
	HandleErr(err, "os.OpenFile", filePth)

	w := bufio.NewWriter(file)

	_, err = w.WriteString(msg)
	HandleErr(err, "w.WriteString", filePth)

	err = w.Flush()
	HandleErr(err, "w.Flush", filePth)

}

func GetDockerfile(file string) string {
	box := packr.New("DockerFile", "../dockerfile")

	s, err := box.FindString(file)

	if err != nil {
		log.Fatal(err)
	}

	return s
}

func Alert(message string) string {
	fmt.Println(message)

	var input string
	_, _ = fmt.Scanln(&input)

	if len(input) < 1 {
		fmt.Println("格式有误，请重新输入")
		Alert(message)
	}

	return input
}

func ReadLine(file string) []string {
	var line []string

	f, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}

	sc := bufio.NewScanner(f)

	for sc.Scan() {
		line = append(line, sc.Text())
	}

	return line
}

func GetEnvVal(file, str string) string {
	var out string
	list := ReadLine(file)

	for _, v := range list {
		if ok := strings.Contains(v, str); ok == true {
			out = v
			break
		}
	}

	return strings.Replace(out, str, "", -1)
}

func DirEmpty(s string) bool {
	dir, err := os.ReadDir(s)

	if err != nil {
		HandleErr(err, "", s)
	}

	if len(dir) > 0 {
		return false
	} else {
		return true
	}
}

func GetFuncName(skip int) string {
	pc, _, _, _ := runtime.Caller(skip)
	f := runtime.FuncForPC(pc)
	return f.Name()
}

func HandleErr(err error, prefix, suffix string) {
	if err == nil {
		return
	}

	funcName := GetFuncName(2)

	log.Fatal("err-func:"+funcName, "|&|", prefix+":"+err.Error(), "|&|", suffix)
}

func InArray(s string, l []string) bool {
	sort.Strings(l)

	index := sort.SearchStrings(l, s)

	if index < len(l) && l[index] == s {
		return true
	}

	return false
}
